/*
 * BmpFileUtils.h
 *
 *  Created on: Dec 7, 2009
 *      Author: tptfc
 */

#ifndef BMPFILEUTILS_H_
#define BMPFILEUTILS_H_

#include <stdio.h>
#include <stdlib.h>

class BmpFileUtils {
private:
	static long getInfoImagem(FILE* inputFile, long offset, int numberOfChars) {
		unsigned char *ptrC;
		long value = 0L;
		unsigned char tmpChar;
		int i;
		float power=1.0;

		ptrC = &tmpChar;

		fseek(inputFile, offset, SEEK_SET);

		//Cálculo do valor por adição de bytes
		for(i=0; i<numberOfChars; i++)  {
			fread(ptrC, sizeof(char), 1, inputFile);
			value = (long)(value + (*ptrC)*(power));
			power=power*256;
		}
		return(value);
	}
public:
	BmpFileUtils();
	virtual ~BmpFileUtils();

	static ImageEntity *read(string path) {
		FILE *bmpInput = fopen(path.c_str(), "rb");

		int width = (int)getInfoImagem(bmpInput, 18, 4);
		int height = (int)getInfoImagem(bmpInput, 22, 4);
		long fileSize = getInfoImagem(bmpInput, 2, 4);

		if(fileSize != (height*width*3+54)){
			printf("\nArquivo de entrada incorreto ou com dimensões desalinhadas...\n");
			exit(0);
		}

		//Alocação Dinâmica de Memória para os arrays Red, Green, Blue e buffChar
		int **redValue = new int*[height];
		for (int i = 0 ; i < height; i++) {
			redValue[i] = new int[width];
		}

		int **greenValue = new int*[height];
		for (int i = 0 ; i < height; i++) {
			greenValue[i] = new int[width];
		}

		int **blueValue = new int*[height];
		for (int i = 0 ; i < height; i++) {
			blueValue[i] = new int[width];
		}

		unsigned char *buffChar = (unsigned char *)malloc((sizeof(unsigned char) * height * width * 3));

		//Inicialização do indexador de buffChar
		long index = 0;

		//Leitura e armazenamento dos dados
		fread(buffChar, sizeof(unsigned char), height*width*3, bmpInput);

		for(int r = 0; r < height; r++) {
			for(int c = 0; c < width; c++) {
				blueValue[r][c] = buffChar[index];
				index++;

				greenValue[r][c] = buffChar[index];
				index++;

				redValue[r][c] = buffChar[index];
				index++;
			}
		}

		fclose(bmpInput);

		return new ImageEntity(width, height, fileSize, redValue, greenValue, blueValue);
	}

	static void write(string originalPath, string path, ImageEntity *imageEntity) {
		FILE *bmpInput = fopen(originalPath.c_str(), "rb");
		FILE *bmpOutput = fopen(path.c_str(), "wb");

		int height = imageEntity->getHeight();
		int width = imageEntity->getWidth();
		unsigned char *buffChar = (unsigned char *)malloc((sizeof(unsigned char) * height * width * 3));

		fseek(bmpInput, 0, SEEK_SET);
		fseek(bmpOutput, 0, SEEK_SET);

		fread(buffChar, sizeof(char), 54, bmpInput);
		fwrite(buffChar, sizeof(char), 54, bmpOutput);

		long index = 0;
		//Escrita dos Arrays Red, Green e Blue ao arquivo de saída
		for(int r = 0; r < height; r++){
		  for(int c = 0; c < width; c++){
			buffChar[index] = (unsigned char) imageEntity->getVectorsB()[r][c];
			index++;
			buffChar[index] = (unsigned char) imageEntity->getVectorsG()[r][c];
			index++;
			buffChar[index] = (unsigned char) imageEntity->getVectorsR()[r][c];
			index++;
		  }
		}

		fwrite(buffChar, sizeof(unsigned char), height*width*3, bmpOutput);

		fclose(bmpInput);
		fclose(bmpOutput);
	}
};

#endif /* BMPFILEUTILS_H_ */
